﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
using FarseerPhysics.DebugView;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using PulseLibrary;
using FarseerPhysics;

namespace PulsePrototype.PulseManagers
{
    public class PhysicsManager : BaseManager
    {
        private World world;
        private SpriteBatch spriteBatch;
        public DebugViewXNA _DebugView;
        public CameraComponent camComp;

        public const float unitToPixel = 100.0f;
        public const float pixelToUnit = 1 / unitToPixel;

        public World World
        {
            get { return this.world; }
        }

        public SpriteBatch SpriteBatch
        {
            get { return spriteBatch; }
        }

        public GraphicsDeviceManager Graphics
        {
            get { return this.Game.Graphics; }
            set { this.Game.Graphics = value; }
        }

        public GraphicsDevice GraphicsDevice
        {
            get { return this.Game.GraphicsDevice; }
        }

        protected override String GetName()
        {
            return "Physics";
        }

        public PhysicsManager(Game1 game)
            : base(game)
        {
            Initialize();
        }

        protected override void Initialize()
        {
            this.world = new World(new Vector2(0, 4.9f));
            this.spriteBatch = Game.SpriteBatch;

            // By default, the ratio is 1 to 100 anyways.
            // ConvertUnits.SetDisplayUnitToSimUnitRatio(100);

            base.Initialize();

        }

        public override void LoadContent()
        {
            if (_DebugView == null)
            {
                _DebugView = new DebugViewXNA(this.world);
                _DebugView.LoadContent(Game.GraphicsDevice, Game.Content);
            }
        }

        public override void Update(GameTime gameTime)
        {
            world.Step((float)gameTime.ElapsedGameTime.TotalSeconds);
        }

        public override void Draw(Microsoft.Xna.Framework.GameTime gameTime)
        {
            if (DebugSettings.PhysicsDebug)
            {
                // The following four lines of code seems messy and needs to be moved somewhere else.
                // All I really need is to get a matrix view with the physics unit conversion applied.
                // Can't be done in the Initialize method because the SceneManager doesn't exist yet.

                // Possibly create a message for passing Matrix values around in the future?

                if (camComp == null)
                {
                    SceneManager sman = (SceneManager)Game.GamePlayScreen1.GetManager("Scene");
                    BaseEntity cameraEntity = sman.GetEntity(Common.RootEntityName);
                    camComp = cameraEntity.GetComponent<CameraComponent>();
                }
                
                Matrix view = camComp.getPhysicsTransformation(Graphics);

                SpriteBatch.Begin();

                Matrix projection = Matrix.CreateOrthographicOffCenter(
                    0f,
                    ConvertUnits.ToSimUnits(GraphicsDevice.Viewport.Width),
                    ConvertUnits.ToSimUnits(GraphicsDevice.Viewport.Height),
                    0f,
                    0f,
                    1f);

                _DebugView.RenderDebugData(ref projection, ref view);

                SpriteBatch.End();
            }
        }
    }
}
